Newer
Older
Import / applications / RocketMan / Source Code / test / Iterators.h
/*
 *  Iterators.h
 *  iphone-gl-app
 *
 *  Created by John Ryland on 15/06/09.
 *  Copyright 2009 InvertedLogic. All rights reserved.
 *
 */

#ifndef ITERATORS_H
#define ITERATORS_H


#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Debug.h"


#ifdef DEBUG
#define BOUNDS_CHECKING		1
#endif


// Syntactic sugar, yummy!
#define foreach(item, items)    /* Iterate for each item in the collection of items. 'item' can refer to the name of an   */ \
								/* existing variable, or it can declare a new variable with the type plus name declared   */ \
								/* in the usual manner. 'items' should be an object of a type that subclasses Iterable.   */ \
								/* 'item' should be of a type that corresponds to the type 'items' is a collection of.    */ \
								for (int i = 0, loop = 0, cnt = items.count(); i < cnt; i++, loop = 0) \
									/* The next for statement loops only once, it is a clever way to have 'item' expanded */ \
									/* by the preprocessor. The block after the foreach statement will then be executed   */ \
									/* with 'item' in the scope and no need to worry about how to handle encapuslating    */ \
									/* braces for an outter block using the preprocessor to declare a new variables.      */ \
									for (item = items[i]; loop < 1; loop++)


// Interfaces
template<typename T>
class Iterable
{
public:
    Iterable();
    Iterable(const Iterable<T> &cpy);
    virtual ~Iterable();

    const Iterable<T> &operator=(const Iterable<T> &cpy);
    void copy(const Iterable<T> &copy);

    int count() const;
	operator const T *() const;
    T &operator[](int);
    const T &operator[](int) const;

protected:
    T *items;
    int cnt;
};


template<typename T>
class List : public Iterable<T>
{
public:
    const List<T> &operator+=(T);
    const List<T> &operator+=(const List<T> &);
};


template<typename T>
class Dict : public Iterable<T>
{
public:
    Dict();
    virtual ~Dict();
    void append(const char *key, T item);
    void remove(const char *key);
    T &find(const char *key);
protected:
    char **keys;
};


template<typename T>
class Map : public Dict<T>
{
public:
    T &operator[](const char *key);

    /* expose the base class operator functions */
    T &operator[](int i) { return (*this)[i]; }
    const T &operator[](int i) const { return (*this)[i]; }
};


template<typename T>
class MultiMap : public Dict<T>
{
public:
    List<T> &operator[](const char *key);

    /* expose the base class operator functions */
    T &operator[](int i) { return (*(Iterable<T>*)this)[i]; }
    //const T &operator[](int i) const { return (*(Iterable<T>*)this)[i]; }
};


// Implementations
template<typename T>
Iterable<T>::Iterable() : items(0), cnt(0)
{
}


template<typename T>
Iterable<T>::Iterable(const Iterable<T> &cpy) : items(0)
{
	copy(cpy);
}


template<typename T>
Iterable<T>::~Iterable()
{
	if (items)
		free(items);
}


template<typename T>
const Iterable<T> &Iterable<T>::operator=(const Iterable<T> &cpy)
{
	copy(cpy);
	return *this;
}


template<typename T>
void Iterable<T>::copy(const Iterable<T> &copy)
{
	items = (T*)realloc(items, sizeof(T) * copy.cnt);
	memcpy(items, copy.items, sizeof(T) * copy.cnt);
	cnt = copy.cnt;
}


template<typename T>
int Iterable<T>::count() const
{
    return cnt;
}


template<typename T>
Iterable<T>::operator const T *() const
{
	return items;
}


template<typename T>
T &Iterable<T>::operator[](int x)
{
    if (items && cnt > x)
        return items[x];
#ifdef BOUNDS_CHECKING
	error("Access past end of the array\n");
#endif
    static T ret;
    return ret;
}


template<typename T>
const T &Iterable<T>::operator[](int x) const
{
    if (items && cnt > x)
        return items[x];
#ifdef BOUNDS_CHECKING
	error("Access past end of the array\n");
#endif
    static T ret;
    return ret;
}


template<typename T>
const List<T> &List<T>::operator+=(T item)
{
    this->cnt++;
    this->items = (T *)realloc(this->items, sizeof(T) * this->cnt);
    this->items[this->cnt - 1] = item;
    return *this;
}


template<typename T>
const List<T> &List<T>::operator+=(const List<T> &others)
{
    int pos = this->cnt;
    this->cnt += others.cnt;
    this->items = (T *)realloc(this->items, sizeof(T) * this->cnt);
    for (int i = 0; i < others.cnt; i++)
        this->items[pos + i] = others.items[i];
    return *this;
}


template<typename T>
Dict<T>::Dict() : Iterable<T>()
{
    keys = 0;
}


template<typename T>
Dict<T>::~Dict()
{
    if (keys)
        for (int i = 0; i < this->cnt; i++)
            free(keys[i]);
    free(keys);
}


template<typename T>
void Dict<T>::append(const char *key, T item)
{
    this->cnt++;
    keys = (char **)realloc(keys, sizeof(char *) * this->cnt);
    this->items = (T*)realloc(this->items, sizeof(T) * this->cnt);
    keys[this->cnt - 1] = strdup(key);
    this->items[this->cnt - 1] = item;
}


template<typename T>
void Dict<T>::remove(const char *key)
{
    for (int i = 0; i < this->cnt; i++)
        if (!strcmp(key,this->keys[i])) {
            free(this->keys[i]);
            this->cnt--;
            for (; i < this->cnt; i++) {
                this->items[i] = this->items[i+1];
                this->keys[i] = this->keys[i+1];
            }
            this->keys = (char **)realloc(this->keys, sizeof(char *) * this->cnt);
            this->items = (T*)realloc(this->items, sizeof(T) * this->cnt);
            return;
        }
}


template<typename T>
T &Dict<T>::find(const char *key)
{
    for (int i = 0; i < this->cnt; i++)
        if (!strcmp(key,this->keys[i]))
            return this->items[i];
    static T ret;
    return ret;
}


template<typename T>
T &Map<T>::operator[](const char *key)
{
    for (int i = 0; i < this->cnt; i++)
        if (!strcmp(key,this->keys[i]))
            return this->items[i];
    static T ret;
    return ret;
}


template<typename T>
List<T> &MultiMap<T>::operator[](const char *key)
{
    static List<T> ret;
    List<T> empty;
    ret = empty;
    for (int i = 0; i < this->cnt; i++)
        if (!strcmp(key,this->keys[i]))
            ret += this->items[i];
    return ret;
}


#endif // ITERATORS_H